Skip to content

Add federation exchange status observability#284

Merged
skulidropek merged 1 commit into
mainfrom
issue-282
May 12, 2026
Merged

Add federation exchange status observability#284
skulidropek merged 1 commit into
mainfrom
issue-282

Conversation

@skulidropek
Copy link
Copy Markdown
Member

Summary

Adds a live observability endpoint for the Lefine/ForgeFed exchange flow so we can see whether docker-git is connected and whether requests/tasks are arriving.

Changes:

  • add GET /federation/exchange/status
  • persist a bounded history of the latest 100 exchange events in federation state
  • record follow.sent, inbox.follow.accept, inbox.follow.reject, inbox.issue.received, and poll.completed
  • expose subscription counters, accepted/pending/rejected counts, issue count, processed outbox item count, lastInboxAt, and lastPollAt
  • document the workflow in packages/api/README.md
  • add service tests for status telemetry and event-history bounds

Related:

How to use

Set the public federation origin to the public URL that Lefine can reach:

export API="https://<public-docker-git-origin>"
export DOCKER_GIT_FEDERATION_PUBLIC_ORIGIN="$API"
export DOCKER_GIT_EXCHANGE_PROJECT_REPO_URL="https://github.com/ProverCoderAI/docker-git"
export DOCKER_GIT_EXCHANGE_AGENT_PROVIDER="codex"

Create or reuse the Lefine exchange subscription:

curl -X POST "$API/federation/exchange/subscriptions" \
  -H 'Content-Type: application/json' \
  --data '{
    "target":"https://problemsets.lefine.pro/actor/code",
    "projectRepoUrl":"https://github.com/ProverCoderAI/docker-git",
    "agentProvider":"codex"
  }'

Check whether the connection is alive:

curl "$API/federation/exchange/status"

Important fields in the response:

  • summary.accepted > 0 means Lefine accepted our Follow subscription.
  • summary.lastInboxAt means something arrived in /federation/inbox, for example Lefine's Accept.
  • summary.lastPollAt means docker-git successfully polled the remote Lefine outbox.
  • summary.issues is the number of ForgeFed issues/Tickets currently persisted by docker-git.
  • summary.processedOutboxItems is the number of outbox items already handled, used for deduplication.
  • recentEvents shows the latest exchange activity: Follow sent, Follow accepted/rejected, issue received, poll completed.

Run a safe manual poll that does not start agents/projects:

curl -X POST "$API/federation/exchange/poll" \
  -H 'Content-Type: application/json' \
  --data '{"target":"code","runTasks":false}'

Run a normal poll that can create docker-git projects/agents when new Create(Ticket) items exist:

curl -X POST "$API/federation/exchange/poll" \
  -H 'Content-Type: application/json' \
  --data '{"target":"code"}'

View persisted incoming issues:

curl "$API/federation/issues"

Expected flow:

  1. Subscription sends ActivityPub Follow to Lefine and records follow.sent.
  2. Lefine answers with Accept into /federation/inbox; status becomes accepted, lastInboxAt is set, and inbox.follow.accept appears in recentEvents.
  3. docker-git polls Lefine's outbox; each poll records poll.completed.
  4. A Lefine Create(Ticket) creates a persisted issue and records inbox.issue.received.
  5. If the Ticket is handled through outbox polling and runTasks is not false, docker-git starts the project/agent flow using the Ticket GitHub URL or DOCKER_GIT_EXCHANGE_PROJECT_REPO_URL fallback.

A subscription by itself does not create a docker-git task. It only establishes the ActivityPub connection. Tasks appear after Lefine publishes/sends a Create(Ticket).

Live smoke result

Smoke-tested with a public Cloudflare origin. Current observed state after subscribing to Lefine:

{
  "summary": {
    "subscriptions": 1,
    "accepted": 1,
    "pending": 0,
    "rejected": 0,
    "issues": 0,
    "processedOutboxItems": 0,
    "lastInboxAt": "2026-05-12T11:33:59.448Z"
  },
  "subscriptions": [
    {
      "target": "https://problemsets.lefine.pro/actor/code",
      "queue": "code",
      "status": "accepted",
      "remoteActor": "https://problemsets.lefine.pro/actor/code",
      "remoteOutbox": "https://problemsets.lefine.pro/outbox/code"
    }
  ]
}

Manual safe poll returned totalItems=0, newItems=0, processedItems=0, so the connection is accepted but Lefine had no new tasks in the outbox at that moment.

Verification

bun run api:typecheck
bun run --cwd packages/api lint
bun run api:test

Result: API tests passed, 18 files / 109 tests.

@skulidropek skulidropek merged commit d9cee20 into main May 12, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant